package codebot.processor.languages;

import codebot.processor.IScreen;
import codebot.processor.logic.Score;
import codebot.processor.logic.State;

/**
 * Specific syntax processor for Java
 */
public class Xml extends Lang {

	protected static int DEPTH = Lang.DEPTH + 1;

	// parameters
	private final static String COLOR_TAG = "rgb(127,0,145)";
	private final static String COLOR_PROPERTY = "rgb(195,117,0)";
	private final static String TAG_PHP_BEGIN = "?php";
	private final static String TAG_PHP_END = "?>";
	private final static String TAG_JS_BEGIN = "script";
	private final static String TAG_JS_END = "</script>";

	/**
	 * @see Lang.java
	 */
	@Override
	public void processSpecificSyntax(IScreen screen, String code, int s, int e) {
		final int codeStart = s - 3; // TODO correct this -3 correction
		// :) Wave's fault
		int i = 0;
		State state = new State(screen, codeStart);
		while (i < code.length()) {
			switch (state.getState()) {
			case 0:
				switch (code.charAt(i)) {
				case '<':
					// a tag name will follow
					state.set(1, i + 1, null, null, null, null, null);
					break;
				}
				break;
			case 1:
				switch (code.charAt(i)) {
				case '>':
					state.set(0, null, i - 1, null, COLOR_TAG, null, null);
					// next follows content (which can also be xml)
					if (TAG_JS_BEGIN.equals(code.substring(state.getStart(),
							state.getEnd() + 1))) {
						final int jsEnd = code.indexOf(TAG_JS_END, i + 1);
						if (jsEnd > i + 1) {
							Lang.getSpecificSyntaxProcessor(Score.sJavascript)
									.processSpecificSyntax(screen, code, i + 1,
											jsEnd);
							i=jsEnd-1;
						}
						state.set(0, null, null, null, null, null, null);
					}
					break;
				case ' ':
				case '\n':
					// we're in a tag definition, expecting properties
					state.set(2, null, i - 1, null, COLOR_TAG, null, null);
					if (TAG_PHP_BEGIN.equals(code.substring(state.getStart(),
							state.getEnd() + 1))) {
						final int phpEnd = code.indexOf(TAG_PHP_END, i + 1);
						if (phpEnd > 0) {
							Lang.getSpecificSyntaxProcessor(Score.sPhp)
									.processSpecificSyntax(screen, code, i,
											i = phpEnd - 1);
							state.set(2, null, null, null, null, null, null);
						}
					}
					break;
				}
				break;
			case 2:
				switch (code.charAt(i)) {
				case ' ':
				case '\n':
					break;
				case '/':
				case '?':
					state.set(5, null, null, null, null, null, null);
					break;
				case '>':
					// next follows content (which can also be xml)
					state.set(0, null, null, null, null, null, null);
					break;
				default:
					// we're now in a property name
					state.set(3, i, null, null, null, null, null);
				}
				break;
			case 3:
				switch (code.charAt(i)) {
				case '=':
					// waiting for the property, including value, to finish
					state.set(4, null, i - 1, null, COLOR_PROPERTY, null, null);
					break;
				}
				break;
			case 4:
				switch (code.charAt(i)) {
				case ' ':
				case '\n':
					state.set(2, null, null, null, null, null, null);
					break;
				case '>':
					// next follows content (which can also be xml)
					state.set(0, null, null, null, null, null, null);
					break;
				}
				break;
			case 5:
				switch (code.charAt(i)) {
				case '>':
					// next follows content (which can also be xml)
					state.set(0, null, null, null, null, null, null);
					break;
				}
				break;
			}
			i++;
		}
	}

	@Override
	public String toString() {
		return "XML";
	}
}
